package com.kproduce.roundcorners.util;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.BlendMode;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;

/**
 * RoundHelper
 *
 * @author kuanggang on 2019/12/10
 * @since 2021-05-21
 */
public class RoundHelper {
    private static final int EIGHT = 8;
    private static final int TWO = 2;
    private Context mContext;
    private Component mView;

    private Paint mPaint;
    private RectFloat mRectF;
    private RectFloat mStrokeRectF;

    private Path mPath;

    private BlendMode blendMode;

    private float[] mRadii;
    private float[] mStrokeRadii;

    private int mWidth;
    private int mHeight;
    private double mStrokeWidth;
    private Color mColor;

    /**
     * init
     *
     * @param context
     * @param attrs
     * @param view
     */
    public void init(Context context, AttrSet attrs, Component view) {
        mColor = attrs.getAttr("rStrokeColor").get().getColorValue();
        mContext = context;
        mView = view;
        mRadii = new float[EIGHT];
        mStrokeRadii = new float[EIGHT];
        mPaint = new Paint();
        mRectF = new RectFloat();
        mStrokeRectF = new RectFloat();
        mPath = new Path();
        blendMode = mPaint.setBlendMode(BlendMode.DST_ATOP);
        mStrokeWidth = attrs.getAttr("rStrokeWidth").get().getFloatValue();
    }

    /**
     * onSizeChanged
     *
     * @param width
     * @param height
     */
    public void onSizeChanged(int width, int height) {
        mWidth = width;
        mHeight = height;
        if (null != mRectF) {
            mRectF.fuse(0, 0, width, height);
        }
        if (null != mStrokeRectF) {
            mStrokeRectF.fuse((float) mStrokeWidth / TWO, (float)mStrokeWidth / TWO,
                    (float)(width - mStrokeWidth / TWO), (float) ((float)height - mStrokeWidth / TWO));
        }
    }

    /**
     * preDraw
     *
     * @param canvas
     * @param width
     * @param height
     */
    public void preDraw(Canvas canvas, int width, int height) {
        this.mWidth = width;
        this.mHeight = height;
        canvas.saveLayer(mRectF, mPaint);
        if (mStrokeWidth > 0) {
            float sx = (float) ((mWidth - TWO * mStrokeWidth) / mWidth);
            float sy = (float) ((mHeight - TWO * mStrokeWidth) / mHeight);

            // 缩小画布，使图片内容不被borders覆盖
            canvas.scale(sx, sy, (float) mWidth / TWO, (float)mHeight / TWO);
        }
    }

    /**
     * 绘制边框
     *
     * @param canvas
     */
    public void drawPath(Canvas canvas) {
        mPaint.reset();
        mPath.reset();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL_STYLE);
        mPaint.setBlendMode(blendMode);
        mPaint.setColor(mColor);
        mPath.addRoundRect(mRectF, mRadii, Path.Direction.COUNTER_CLOCK_WISE);
        canvas.drawPath(mPath, mPaint);
        mPaint.setBlendMode(null);
        canvas.restore();
        if (mStrokeWidth > 0) {
            mPaint.setStyle(Paint.Style.STROKE_STYLE);
            mPaint.setStrokeWidth((float) mStrokeWidth);
            mPaint.setColor(mColor);
            mPath.reset();
            mPath.addRoundRect(mStrokeRectF, mStrokeRadii, Path.Direction.COUNTER_CLOCK_WISE);
            canvas.drawPath(mPath, mPaint);
        }
    }


    /**
     * setRadius
     *
     * @param radiusDp
     */
    public void setRadius(float radiusDp) {
        if (mContext == null) {
            return;
        }
        if (mView != null) {
            mView.invalidate();
        }
    }

    /**
     * setRadius
     *
     * @param radiusTopLeftDp
     * @param radiusTopRightDp
     * @param radiusBottomLeftDp
     * @param radiusBottomRightDp
     */
    public void setRadius(float radiusTopLeftDp, float radiusTopRightDp,
                          float radiusBottomLeftDp, float radiusBottomRightDp) {
        if (mContext == null) {
            return;
        }
        if (mView != null) {
            mView.invalidate();
        }
    }

    /**
     * setRadiusLeft
     *
     * @param radiusDp
     */
    public void setRadiusLeft(float radiusDp) {
        if (mContext == null) {
            return;
        }
        if (mView != null) {
            mView.invalidate();
        }
    }

    /**
     * setRadiusRight
     *
     * @param radiusDp
     */
    public void setRadiusRight(float radiusDp) {
        if (mContext == null) {
            return;
        }
        if (mView != null) {
            mView.invalidate();
        }
    }

    /**
     * setRadiusTop
     *
     * @param radiusDp
     */
    public void setRadiusTop(float radiusDp) {
        if (mContext == null) {
            return;
        }
        if (mView != null) {
            mView.invalidate();
        }
    }

    /**
     * setRadiusBottom
     *
     * @param radiusDp
     */
    public void setRadiusBottom(float radiusDp) {
        if (mContext == null) {
            return;
        }
        if (mView != null) {
            mView.invalidate();
        }
    }

    /**
     * setRadiusTopLeft
     *
     * @param radiusDp
     */
    public void setRadiusTopLeft(float radiusDp) {
        if (mContext == null) {
            return;
        }
        if (mView != null) {
            mView.invalidate();
        }
    }

    /**
     * setRadiusTopRight
     *
     * @param radiusDp
     */
    public void setRadiusTopRight(float radiusDp) {
        if (mContext == null) {
            return;
        }
        if (mView != null) {
            mView.invalidate();
        }
    }

    /**
     * setRadiusBottomLeft
     *
     * @param radiusDp
     */
    public void setRadiusBottomLeft(float radiusDp) {
        if (mContext == null) {
            return;
        }
        if (mView != null) {
            mView.invalidate();
        }
    }

    /**
     * setRadiusBottomRight
     *
     * @param radiusDp
     */
    public void setRadiusBottomRight(float radiusDp) {
        if (mContext == null) {
            return;
        }
        if (mView != null) {
            mView.invalidate();
        }
    }

    /**
     * setStrokeWidth
     *
     * @param widthDp
     */
    public void setStrokeWidth(float widthDp) {
        if (mContext == null) {
            return;
        }
        mStrokeWidth = DensityUtil.dip2px(mContext, widthDp);
        if (mView != null) {
            onSizeChanged(mWidth, mHeight);
            mView.invalidate();
        }
    }

    /**
     * setStrokeColor
     *
     * @param color
     */
    public void setStrokeColor(int color) {
        if (mView != null) {
            mView.invalidate();
        }
    }

    /**
     * setStrokeWidthColor
     *
     * @param widthDp
     * @param color
     */
    public void setStrokeWidthColor(float widthDp, int color) {
        if (mContext == null) {
            return;
        }
        mStrokeWidth = DensityUtil.dip2px(mContext, widthDp);
        if (mView != null) {
            onSizeChanged(mWidth, mHeight);
            mView.invalidate();
        }
    }
}
